package com.loe.ui.view

import android.annotation.SuppressLint
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import android.widget.TextView
import androidx.annotation.Keep
import com.loe.mvp.ext_app.color
import com.loe.mvp.ext_java.float
import com.loe.mvp.ext_view.addTextAfterListener
import com.loe.ui.*
import com.loe.ui.api.IUiView
import com.loe.ui.api.TextViewApi
import com.loe.ui.page.UiPage
import com.quickjs.JSArray
import com.quickjs.JSObject

@Keep
@SuppressLint("AppCompatCustomView")
open class UiTextView : TextView, IUiView
{
    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    {
        initXML(attrs)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    {
        initXML(attrs)
    }

    private fun initXML(attrs: AttributeSet)
    {
    }

    override val jsObject by lazy { TextViewApi(this).jsObject }

    override fun setUI(ui: JSObject, uiPage: UiPage?): View
    {
        // click
        ui.gotHasBoolean("isClick") { setClick(it) }
        // textColor
        if (ui.contains("textColor"))
        {
            setTextColor(ui.gotString("textColor").color)
        } else
        {
            setTextColor(context.color(R.color.textColor))
        }

        // gravity
        ui.gotHasGravity("gravity") { gravity = it }

        // isTextSelectable
        ui.gotHasBoolean("isTextSelectable") { setTextIsSelectable(it) }
        // hint
        ui.gotHasString("hint") { hint = it }
        // hintColor
        ui.gotHasString("hintColor") { setHintTextColor(it.color) }
        // minLines
        ui.gotHasInt("minLines") { minLines = it }
        // maxLines
        ui.gotHasInt("maxLines") { maxLines = it }
        // ellipsize
        ui.gotHasString("ellipsis") { ellipsize = TextUtils.TruncateAt.valueOf(it.toUpperCase()) }

        // bold
        ui.gotHasBoolean("bold") { setBold(it) }
        // italic
        ui.gotHasBoolean("italic") { setItalic(it) }
        // textStyle
        ui.gotHasString("textStyle") { setTextStyle(it) }

        // onText
        ui.gotHasFunction("onText")
        { callback ->
            setTextListener { callback.call(jsObject, JSArray(jsContext).push(it)) }
        }

        // textSize
        ui.gotHasString("textSize") { setTextSize(it) }

        // autoVisible
        ui.gotHasBoolean("autoVisible") { isAutoVisible = it }
        // text
        ui.gotHasString("text") { setAutoText(it) }

        // image
        ui.gotHas("image")
        {
            image = it
            imageTop = ui.gotString("imageTop", "0").px
            imageWidth = ui.gotString("imageWidth", "14").px
            imageHeight = ui.gotString("imageHeight", "14").px
            imagePadding = ui.gotString("imagePadding", "4").px
            imageColor = ui.gotString("imageColor")
            imageDirect = ui.gotString("imageDirect")

            notifyImage()
        }

        return this
    }

    override var onSelect: (() -> Unit)? = null

    /******************************************* 图片 *******************************************/

    var image: Any? = null
    var imageTop = 0
    var imageWidth = 0
    var imageHeight = 0
    var imagePadding = 0
    var imageColor = ""
    var imageDirect = ""

    fun notifyImage()
    {
        if (image is JSObject)
        {
            setImage((image as JSObject).shape)
        } else
        {
            context.getUrlDrawable(image.toString()) { setImage(it) }
        }
    }

    fun setImage(it: Drawable)
    {
        it.setBounds(0, imageTop, imageWidth, imageHeight + imageTop)
        if (imageColor.isNotEmpty())
        {
            it.colorFilter = PorterDuffColorFilter(imageColor.color, PorterDuff.Mode.SRC_ATOP)
        }
        val ds = compoundDrawables
        when (imageDirect)
        {
            "top" -> ds[1] = it
            "right" -> ds[2] = it
            "bottom" -> ds[3] = it
            else -> ds[0] = it
        }
        setCompoundDrawables(ds[0], ds[1], ds[2], ds[3])
        compoundDrawablePadding = imagePadding
    }

    /******************************************* 其他 *******************************************/

    var isAutoVisible: Boolean = false

    fun setAutoText(s: String?)
    {
        if (isAutoVisible) visibility = if (s == null || s.trim().isEmpty()) GONE else VISIBLE
        text = s
    }

    fun setClick(isClick: Boolean)
    {
        isAlpha = isClick
        isClickable = isClick
    }

    private var isAlpha = false

    override fun setTextColor(color: Int)
    {
        if (isAlpha)
        {
            val states = arrayOfNulls<IntArray>(3)
            states[0] = intArrayOf(android.R.attr.state_enabled, -android.R.attr.state_pressed)
            states[1] = intArrayOf(android.R.attr.state_enabled, android.R.attr.state_pressed)
            states[2] = intArrayOf(-android.R.attr.state_enabled)
            val alphaColor = (0xbb shl 24) + (color and 0xFFFFFF)
            setTextColor(ColorStateList(states, intArrayOf(color, alphaColor, alphaColor)))
        } else
        {
            super.setTextColor(color)
        }
    }

    private var onText: ((s: String) -> Unit)? = null

    private val addTextChanged by lazy {
        addTextAfterListener()
        {
            onText?.invoke(it)
        }
    }

    fun setTextListener(onText: (s: String) -> Unit)
    {
        this.onText = onText
        addTextChanged
    }

    /***************************************** 文本样式 ***************************************/

    fun setBold(bold: Boolean)
    {
        typeface = if (bold) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
    }

    fun setItalic(italic: Boolean)
    {
        setTypeface(Typeface.DEFAULT, if (italic) Typeface.ITALIC else Typeface.NORMAL)
    }

    fun setTextStyle(textStyle: String)
    {
        when (textStyle)
        {
            "bold" -> paint.flags = Paint.FAKE_BOLD_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG
            "delete" -> paint.flags = Paint.STRIKE_THRU_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG
            "under" -> paint.flags = Paint.UNDERLINE_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG
            // normal
            else -> paint.flags = Paint.ANTI_ALIAS_FLAG
        }
    }

    fun setTextSize(size: String)
    {
        if (size.endsWith("px"))
        {
            setTextSize(TypedValue.COMPLEX_UNIT_PX, size.replace("px", "").float)
        } else
        {
            setTextSize(TypedValue.COMPLEX_UNIT_DIP, size.float)
        }
    }
}